#include "TestCuboid.h"
#include "TextureManager.h"
#include "FragmentationDemo.h"
#include "Fragment.h"
#include "ModalFilter.h"
#include "ModalFilterSystem.h"

#include <assert.h>
#include "GLCuboid.h"
#include <GL\glut.h>

TestCuboid::TestCuboid() : m_fractured(false)
{

}
TestCuboid::TestCuboid(const Vec3f& pos, const Vec3f& halfExtents, int numFragments) : m_fractured(false)
{
	
	//Define dimensions and create vertices for drawing
	m_pCuboid = new GLCuboid(halfExtents);
	m_materialDensity = 1;
	m_numFragments = numFragments;
	
	//Create bullet rigid body
	m_halfExtents = halfExtents;
	btBoxShape* shape = new btBoxShape(btVector3(halfExtents.X, halfExtents.Y, halfExtents.Z));
	CreateRigidBody(shape, 5);

	float pitchScaler = 50;

	m_pRigidBody->setRestitution(0.9f);

	m_pModalFilterSystem = new ModalFilterSystem(0.05, 0.4, 200, 15000);

	//Create modal filter system
	m_pModalFilterSystem->AddFilter(new SinSweepFilter(halfExtents.LengthSqr() * pitchScaler, 50, 0.05));
	m_pModalFilterSystem->AddFilter(new DecayingSinFilter((halfExtents.X * 2 * pitchScaler), 0.1));
	m_pModalFilterSystem->AddFilter(new DecayingSinFilter((halfExtents.Y * 2 * pitchScaler), 0.1));
	m_pModalFilterSystem->AddFilter(new DecayingSinFilter((halfExtents.Z * 2 * pitchScaler), 0.1));

	SetPos(pos);

	

}

void TestCuboid::Draw()
{
	if(!m_fractured)
	{
		glPushMatrix();

		btTransform btTrans;
		m_pMotionState->getWorldTransform(btTrans);
		btTrans.getOpenGLMatrix(m_mat.m_matrix);
		m_mat.MultiOpenGL();

		//TheTextureManager::Instance()->DrawTexture(m_texPath);

		m_pCuboid->Draw();

		glPopMatrix();
	}
	else
	{
		std::vector<Fragment*>::iterator it = m_fragments.begin();
		std::vector<Fragment*>::iterator end = m_fragments.end();
		for( ; it != end; ++it)
		{
			(*it)->Draw();
		}
	}

	
	
}

void TestCuboid::Update()
{
	
} 

void TestCuboid::Shatter()
{
			btVector3 bbmax(m_halfExtents.X, m_halfExtents.Y, m_halfExtents.Z);
			btVector3 bbmin = -bbmax;
			btVector3 bbt = m_pRigidBody->getWorldTransform().getOrigin();
			//btVector3 bbt(m_pos.X, m_pos.Y, m_pos.Z);
			btVector3 diff = bbmax - bbmin;
			btAlignedObjectArray<btVector3> points;
			btVector3 point;

			assert(m_pRigidBody);
			btQuaternion bbq = m_pRigidBody->getOrientation();

			for (unsigned int i=0; i < m_numFragments; i++) 
			{

				// Place points within box area (points are in world coordinates)
				point = quatRotate(bbq, btVector3(btScalar(rand() / btScalar(RAND_MAX)) * diff.x() -diff.x()/2., btScalar(rand() / btScalar(RAND_MAX)) * diff.y() -diff.y()/2., btScalar(rand() / btScalar(RAND_MAX)) * diff.z() -diff.z()/2.)) + bbt;
				points.push_back(point);
			}


			voronoiBBShatter(points, bbmin, bbmax, bbq, bbt, m_materialDensity, m_pRigidBody->getLinearVelocity());
			TheFragmentationDemo::Instance()->AddOrRemoveRigidBody(false, m_pRigidBody);
			m_fractured = true;
}

void TestCuboid::Collided(btManifoldPoint& contact)
{
	
	if(m_fractured)
	{
		//assert(0);
	}
	else
	{
		float force = contact.getAppliedImpulse();
		float volumeComp = m_halfExtents.Length();
		m_pModalFilterSystem->Process(force);
		if(force > volumeComp)
		{
			Shatter();
		}
	}
}

TestCuboid::~TestCuboid()
{
	//delete m_pCuboid;
}